package com.example.server.handler;

import com.example.commons.*;
import com.example.commons.future.MsgFuture;
import com.example.commons.handler.HandlerRegister;
import com.example.commons.model.BizReqMsg;
import com.example.commons.model.BizResMsg;
import com.example.commons.model.LoginReqMsg;
import com.example.commons.model.LoginResMsg;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.ExecutorService;

/**
 * @author cdw
 * <p>
 * netty服务端处理器
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private MsgPool pool;

    /**
     * 业务处理线程池，防止业务响应慢阻塞通讯线程
     */
    @Autowired
    private ExecutorService executor;

    private AttributeKey<String> clientAttr = AttributeKey.valueOf("clientId");

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("Channel active......");
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Channel channel = ctx.channel();
        executor.execute(() -> {
            if (msg instanceof LoginReqMsg) {
                log.info("服务器收到客户端【登录】消息: {}", msg.toString());
                LoginReqMsg loginReqMsg = (LoginReqMsg) msg;

                String clientId = loginReqMsg.getClientId();
                pool.putClient(clientId, channel);
                channel.attr(clientAttr).set(clientId);

                LoginResMsg loginResMsg = new LoginResMsg();
                loginResMsg.setResult(true);

                ctx.writeAndFlush(loginResMsg);

            } else if (msg instanceof BizReqMsg) {
                log.info("服务器收到客户端【业务】消息: {}", msg.toString());
                BizReqMsg bizReqMsg = (BizReqMsg) msg;
                BizResMsg bizResMsg = new BizResMsg();
                bizResMsg.setReqId(bizReqMsg.getReqId());
                bizResMsg.setResult(bizReqMsg.getData());
                ctx.writeAndFlush(bizResMsg);

                log.info("client -> server 回应 [{}]", msg);
            } else if (msg instanceof BizResMsg) {
                BizResMsg bizResMsg = (BizResMsg) msg;
                MsgFuture future = pool.get(bizResMsg.getReqId());
                if (future != null) {
                    future.setRes(bizResMsg);
                }

                log.info("server -> client 返回 [{}]", msg);
            } else {
                ctx.write("其他操作成功");
            }
            ctx.flush();
        });
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String clientId = ctx.channel().attr(clientAttr).get();
        if (StringUtils.hasText(clientId)) {
            log.info("客户端断开连接[{}]", clientId);
            pool.removeClient(clientId);
        }
        ctx.channel().close();
    }

    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}